# -*- coding: utf-8 -*-
# created on 2016/6/1
from sympy import solveset, Abs
from mathsolver.functions.base import *
from mathsolver.functions.shuyushi import ShuYuShiFenShi001
from mathsolver.functions.sympy_utils import ReplaceAll
from sympy.abc import x


# 根据方程的解求参：输入的解为一个等式：如x=3
class DaiRuEquation(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        symbol = default_symbol(f1 - f2)
        f3 = symbol
        if isinstance(args[1], BaseEq):
            f3, f4 = args[1].sympify()
        elif isinstance(args[1], BaseSymbolValue):
            jie = args[1].sympify()
            f3 = jie.keys()[0]
            f4 = jie[jie.keys()[0]].args[0]
        else:
            f4 = args[1].sympify()
        new_f1 = f1.subs({f3: f4})
        new_f2 = f2.subs({f3: f4})
        self.steps.append(["将%s带入方程得" % self.output_eq([f3, f4]), self.output_eq([new_f1, new_f2])])
        self.label.add("根据方程的解求参")
        self.output.append(BaseEq([new_f1, new_f2]))
        return self


class DaiRuFangChen(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        if len(args) == 2:

            f3, f4 = args[1].sympify()
        elif len(args) == 3:
            f3 = args[1].sympify() if args[1] else x
            f4 = args[2].sympify()

        new_f1 = f1.subs({f3: f4})
        new_f2 = f2.subs({f3: f4})

        self.steps.append(["将%s带入方程得" % self.output_eq([f3, f4]), self.output_eq([new_f1, new_f2])])
        self.label.add("根据方程的解求参")
        self.output.append(BaseEq([new_f1, new_f2]))
        return self


# 根据方程的解求参: 输入的解为一个式子
class DaiRuFangChen001(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        if isinstance(args[1], BaseSymbolValue):
            jie = args[1].sympify()
            root = jie[jie.keys()[0]].args[0]
        else:
            root = args[1].sympify()
        f = (f1 - f2).expand()
        symbol = default_symbol(f)

        new_f = f.subs({symbol: root})

        self.steps.append(["将根代入方程，得", BaseEq([new_f, S.Zero]).printing()])
        self.label.add("根据方程的根求参")
        self.output.append(BaseEq([new_f, S.Zero]))
        return self


# 根据多元方程的一组解求参
class DaiRuFangChenZu(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        if isinstance(args[1], BaseSymbolValue):
            answers = args[1].sympify()
            answers_keys = answers.keys()
            subs = {answers_keys[0]: answers[answers_keys[0]].args[0],
                    answers_keys[1]: answers[answers_keys[1]].args[0]}
        else:
            eqs = args[1].sympify()
            subs = dict([(sym, value) for sym, value in eqs])

        new_f1 = f1.subs(subs)
        new_f2 = f2.subs(subs)

        self.steps.append(["将解带入方程得", self.output_eq([new_f1, new_f2])])
        self.label.add("根据多元方程的一组解求参")
        self.output.append(BaseEq([new_f1, new_f2]))
        return self


# 根据方程组的解求参
class DaiRuFangChenZu002(BaseFunction):
    def solver(self, *args):
        eqs = args[0].sympify()
        target_eqs = args[1].sympify()
        if isinstance(args[0], BaseSymbolValue):
            subs = {eqs.keys()[0]: eqs[eqs.keys()[0]].args[0], eqs.keys()[1]: eqs[eqs.keys()[1]].args[0]}
        else:
            subs = dict([(sym, value) for sym, value in eqs])

        new_eqs = []
        for f1, f2 in target_eqs:
            new_f1 = f1.subs(subs)
            new_f2 = f2.subs(subs)
            new_eqs.append([new_f1, new_f2])

        self.steps.append(["将解带入方程组得", self.output_eqs(new_eqs)])
        self.label.add("根据方程组的解求参")
        self.output.append(BaseEqs(new_eqs))
        return self


def interval_zhengshujie(interval, subs):
    ll, r, lopen, ropen = interval.args
    if "正" in subs:
        if "非" in subs:
            assert ll.is_finite, "must be close interval"
            if r >= 0:
                r, ropen = S.Zero, False
        else:
            assert r.is_finite, "must be close interval"
            if ll <= 0:
                ll, lopen = S.Zero, True
    elif "负" in subs:
        if "非" in subs:
            assert r.is_finite, "must be close interval"
            if ll <= 0:
                ll, lopen = S.Zero, False
        else:
            assert ll.is_finite, "must be close interval"
            if r >= 0:
                r, ropen = S.Zero, True
    elif "最大" in subs and not l.is_finite:
        ll = sympify(-500)
    elif "最小" in subs and not r.is_finite:
        r = sympify(500)

    assert ll.is_finite and r.is_finite, "must be close interval"
    if ll.is_Integer:
        if lopen:
            left = ll + 1
        else:
            left = ll
    else:
        if ll > 0:
            left = int(ll) + 1
        else:
            left = int(ll)

    if r.is_Integer:
        if ropen:
            right = r - 1
        else:
            right = r
    else:
        if r > 0:
            right = int(r)
        else:
            right = int(r) - 1

    answer = range(left, right + 1)

    if "最大" in subs:
        answer = [max(answer)]
    elif "最小" in subs:
        answer = [min(answer)]
    return answer


# 不等式的特殊整数解问题
class ZhenShuJie(BaseFunction):
    def solver(self, *args):
        subs = args[1]
        for key in args[0].value:
            symbol = key
            interval = args[0].value[key]
            if isinstance(interval, Union):
                intervals = interval.args
            else:
                intervals = [interval]
            answers = []
            if len(intervals) == 1:
                for inter in intervals:
                    answers = interval_zhengshujie(inter, subs)
            else:
                for inter in intervals:
                    answer = interval_zhengshujie(inter, subs)
                    answers.extend(answer)
                if "最大" in subs:
                    answer_max = [max(answers)]
                    answers = answer_max
                elif "最小" in subs:
                    answer_min = [min(answers)]
                    answers = answer_min
            self.steps.append(["所以：", self.output_answer({symbol: answers})])
            self.output.append(BaseSymbolValue({symbol: answers}))
        self.label.add("不等式的特殊整数解问题")
        return self


# 解个数问题
class ZhenShuJieNumber(BaseFunction):
    def solver(self, *args):
        answer = args[0].value
        answer1 = answer[answer.keys()[0]]
        if type(answer1) is Interval:
            self.steps.append(["", "解的个数为无数个"])
        else:
            answer_number = len(answer1)
            self.steps.append(["解的个数为", BaseNumber(answer_number).printing()])
            self.output.append(BaseNumber(answer_number))
        self.label.add("解个数问题")
        return self


def stepfun_left(xx, c):
    if xx > c:
        return 0.0
    else:
        return 1.0


def stepfun_right(xx, c):
    if xx <= c:
        return 0.0
    else:
        return 1.0


def rectangle(xx, c0, c1):
    if c0 < xx < c1:
        return 1.0
    else:
        return 0.0


# 将方程化为一般形式
class YiBanXingShi(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        f = (f1 - f2).expand().simplify()
        self.steps.append(["方程的一般形式为:", self.output_eq([f, S.Zero])])
        self.label.add("将方程化为一般形式")
        return self


# 方程的解是正数，求参
class IsZhenShu(BaseFunction):
    op = ">"
    condition = "正数"
    label_answer = "值为正数，求参"

    def solver(self, *args):
        ineqs = []
        if isinstance(args[0], BaseSymbolValue):
            symbol_value = args[0].sympify()
            for key, values in symbol_value.items():
                for value in values:
                    ineqs.append([value, self.op, S.Zero])
        else:
            symbol_value = args[0].sympify()
            ineqs.append([symbol_value, self.op, S.Zero])
        if len(ineqs) > 1:
            self.output.append(BaseIneqs(ineqs))
            self.steps.append(["∴", self.output_eqs(ineqs)])
        else:
            self.output.append(BaseIneq(ineqs[0]))
            self.steps.append(["∴", self.output_eq(ineqs[0])])
        self.label.add(self.label_answer)
        return self


# 方程的解是负数，求参
class IsFuShu(IsZhenShu):
    op = "<"
    condition = "负数"
    label_answer = "值为负数，求参"


# 方程的解是非负数，求参
class IsFeiFuShu(IsZhenShu):
    op = ">="
    condition = "非负数"
    label_answer = "值为非负数，求参"


class IsFeiZhengShu(IsZhenShu):
    op = "<="
    condition = "非正数"
    label_answer = "值为非正数，求参"


class FangChenDingYiYu(BaseFunction):
    def solver(self, *args):
        f1, f2 = args[0].sympify()
        target_symbol = default_symbol(f2, args, self)

        try:
            res = ShuYuShiFenShi001().solver(BasePoly(f1 - f2)).output[0]
            if isinstance(res, BaseIneq):
                ineqs = [res.sympify()]
            elif isinstance(res, BaseIneqs):
                ineqs = res.sympify()
        except Exception:
            ineqs = []

        if str(f1) != "y":
            f = f1 - f2
            f = ReplaceAll().replace(f, lambda xx: isinstance(xx, Abs) or (xx.is_Pow and len(xx.free_symbols) > 0 and (xx.args[1].is_even or (1 / xx.args[1]).is_even)))
            symbols = f.free_symbols
            if len(symbols) == 2 and target_symbol in symbols and sympify("t1") in symbols:
                sym = symbols.difference([target_symbol]).pop()
                ineqs.append([list(solveset(f, sym))[0], ">=", S.Zero])

        if len(ineqs) == 1:
            ineq = ineqs[0]
            self.steps.append(["依题意，得：", self.output_eq(ineq)])
            self.output.append(BaseIneq(ineq))
            # self.new_questions.append(BaseIneq(ineq))
        else:
            self.steps.append(["依题意，得：", self.output_eqs(ineqs)])
            self.output.append(BaseIneqs(ineqs))
        assert len(ineqs) > 0
        return self


class FangCheng01(BaseFunction):
    def solver(self, *args):
        eq = args[0].sympify()
        answer = args[1].sympify()
        target_symbol = answer.keys()[0]
        target_value = answer[target_symbol].args[0]
        new_left = eq[0].subs({target_symbol: target_value})
        new_right = eq[1].subs({target_symbol: target_value})
        self.steps.append(["将%s = %s代入方程,得" % (new_latex(target_symbol), new_latex(target_value)),
                           BaseEq([new_left, new_right]).printing()])
        self.output.append(BaseEq([new_left, new_right]))
        return self


# 由两个方程得到方程组
class GouChengEqs(BaseFunction):
    def solver(self, *args):
        eq1 = args[0].sympify()
        eq2 = args[1].sympify()
        self.steps.append(["∴", BaseEqs([eq1, eq2]).printing()])
        self.output.append(BaseEqs([eq1, eq2]))
        return self


# 由两个方程得到方程组
class GouChengIneqs(BaseFunction):
    def solver(self, *args):
        ineq1 = args[0].sympify()
        ineq2 = args[1].sympify()
        self.steps.append(["∴", BaseIneqs([ineq1, ineq2]).printing()])
        self.output.append(BaseIneqs([ineq1, ineq2]))
        return self


if __name__ == '__main__':
    pass
